package com.hzy.system.service.impl;

import com.hzy.infrastructure.config.AdminAppConfig;
import com.hzy.infrastructure.exception.MessageBox;
import com.hzy.infrastructure.security.JwtTokenUtils;
import com.hzy.system.domain.*;
import com.hzy.system.domain.bo.AccountContext;
import com.hzy.system.domain.vo.AuthUserVo;
import com.hzy.system.domain.vo.UpdatePasswordVo;
import com.hzy.system.mapper.ISysUserMapper;
import com.hzy.system.service.*;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 账户服务
 *
 * @author hechuangcd
 */
@Service
public class AccountServiceImpl implements IAccountService {

    private AccountContext accountContext;
    /**
     * 记录上次token的字符串
     */
    private String lastTokenValue;
    private final HttpServletRequest request;
    private final ISysUserMapper sysUserMapper;
    private final AdminAppConfig adminAppConfig;
    private final ISysUserRoleService sysUserRoleService;
    private final ISysRoleService sysRoleService;
    private final ISysUserPostService sysUserPostService;
    private final ISysPostService sysPostService;
    private final ISysOrganizationService sysOrganizationService;

    public AccountServiceImpl(HttpServletRequest request, ISysUserMapper sysUserMapper, AdminAppConfig adminAppConfig, ISysUserRoleService sysUserRoleService, ISysRoleService sysRoleService, ISysUserPostService sysUserPostService, ISysPostService sysPostService, ISysOrganizationService sysOrganizationService) {

        this.sysUserMapper = sysUserMapper;
        this.sysUserRoleService = sysUserRoleService;
        this.sysRoleService = sysRoleService;
        this.sysUserPostService = sysUserPostService;
        this.sysPostService = sysPostService;
        this.sysOrganizationService = sysOrganizationService;
        this.accountContext = null;
        this.request = request;
        this.adminAppConfig = adminAppConfig;
    }

    @Override
    public String getToken() {
        return this.request.getHeader(adminAppConfig.getTokenKey());
    }

    @Override
    public AccountContext getAccountContext() {
        String tokenValue = this.getToken();
        if (Strings.isEmpty(tokenValue)) {
            return null;
        }

        // 验证 token 是否有效
        SysUser sysUser = null;
        try {
            sysUser = JwtTokenUtils.unSign(tokenValue, SysUser.class);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

        if (ObjectUtils.isEmpty(sysUser)) {
            return null;
        }

        //如果用户信息一直没变则返回当前
        if (tokenValue.equals(this.lastTokenValue) && this.accountContext != null && this.accountContext.getId().equals(sysUser.getId())) {
            this.lastTokenValue = tokenValue;
            return this.accountContext;
        }

        //获取当前用户信息
        this.lastTokenValue = tokenValue;
        this.accountContext = new AccountContext();
        sysUser = this.sysUserMapper.selectById(sysUser.getId());
        BeanUtils.copyProperties(sysUser, this.accountContext);

        // 查询 角色id 集合
        List<String> roleIds = this.sysUserRoleService.lambdaQuery()
                .eq(SysUserRole::getUserId, sysUser.getId())
                .select(SysUserRole::getRoleId).list()
                .stream()
                .map(SysUserRole::getRoleId)
                .collect(Collectors.toList());
        //获取角色集合
        List<SysRole> sysRoles = sysRoleService.lambdaQuery().in(SysRole::getId, roleIds).list();
        // 是否超级管理员角色
        boolean isAdministrator = roleIds.contains(this.adminAppConfig.getAdminRoleId());
        // 查询岗位id 集合
        List<String> postIds = this.sysUserPostService.lambdaQuery()
                .eq(SysUserPost::getUserId, sysUser.getId())
                .select(SysUserPost::getPostId).list()
                .stream()
                .map(SysUserPost::getPostId)
                .collect(Collectors.toList());
        //获取岗位集合
        List<SysPost> sysPosts = this.sysPostService.lambdaQuery().in(SysPost::getId, postIds).list();
        //获取当前登陆人的组织机构信息
        SysOrganization sysOrganization = this.sysOrganizationService.getById(sysUser.getOrganizationId());

        // 组合账户信息
        this.accountContext.setAppTitle(this.adminAppConfig.getTitle());
        this.accountContext.setSysRoles(sysRoles);
        this.accountContext.setRoleIds(roleIds);
        this.accountContext.setIsAdministrator(isAdministrator);
        this.accountContext.setPostIds(postIds);
        this.accountContext.setSysPosts(sysPosts);
        this.accountContext.setSysOrganization(sysOrganization);
        return this.accountContext;
    }

    @Override
    public void setAccountContext(AccountContext accountContext) {
        this.accountContext = accountContext;
    }

    @Override
    public String checkAccountAsync(AuthUserVo authUserVo) {
        if (Strings.isEmpty(authUserVo.getUserName())) {
            MessageBox.show("请输入 账户名称!");
        }

        if (Strings.isEmpty(authUserVo.getUserPassword())) {
            MessageBox.show("请输入 账户密码!");
        }

        SysUser sysUser = this.sysUserMapper.getUserByLoginName(authUserVo.getUserName());

        if (sysUser == null) {
            MessageBox.show("账户不存在!");
        }

        // 判断密码
        if (!sysUser.getPassword().equals(authUserVo.getUserPassword())) {
            MessageBox.show("账户密码错误!");
        }

        // Jwt （30L * 1000L * 60L） 30分钟
        return JwtTokenUtils.sign(sysUser, (60L * 1000L * 60L) * 2);
    }

    @Override
    public Integer changePassword(UpdatePasswordVo updatePasswordVo) {
        if (ObjectUtils.isEmpty(updatePasswordVo.getOldPwd())) {
            MessageBox.show("旧密码不能为空！");
        }

        if (ObjectUtils.isEmpty(updatePasswordVo.getNewPwd())) {
            MessageBox.show("新密码不能为空！");
        }

        if (ObjectUtils.isEmpty(updatePasswordVo.getQrPwd())) {
            MessageBox.show("确认密码不能为空！");
        }

        if (!updatePasswordVo.getNewPwd().equals(updatePasswordVo.getQrPwd())) {
            MessageBox.show("两次密码不一致！");
        }

        SysUser sysUser = this.sysUserMapper.selectById(this.accountContext.getId());
        if (!updatePasswordVo.getOldPwd().equals(sysUser.getPassword())) {
            MessageBox.show("旧密码不正确！");
        }

        sysUser.setPassword(updatePasswordVo.getNewPwd());
        return this.sysUserMapper.updateById(sysUser);
    }
}
